{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deep Neural Network (DNN) \n",
    "\n",
    "### Regularization of DNN [256,256,256,256] with max-norm regularization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Get the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stored variables and their in-db values:\n",
      "X_32test_std              -> defaultdict(<class 'list'>, {0: array([[ 0.7957011\n",
      "X_32train_std             -> array([[-0.44445615,  0.62874736, -0.19049071, ...\n",
      "X_test                    -> defaultdict(<class 'list'>, {0: array([[[-0.004097\n",
      "X_test_std                -> defaultdict(<class 'list'>, {0: array([[ 0.8784659\n",
      "X_train                   -> array([[[-0.00304779,  0.0030504 , -0.00249425, ..\n",
      "X_train_std               -> array([[-0.44445615,  0.62874736, -0.19049071, ...\n",
      "snrs                      -> [-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, \n",
      "y_32_test                 -> defaultdict(<class 'list'>, {0: array([6, 7, 1, ..\n",
      "y_32_train                -> array([7, 2, 4, ..., 5, 5, 3])\n",
      "y_test                    -> defaultdict(<class 'list'>, {0: array([3, 2, 5, ..\n",
      "y_train                   -> array([7, 2, 4, ..., 5, 5, 3])\n"
     ]
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from collections import defaultdict\n",
    "from time import time\n",
    "from functools import partial\n",
    "\n",
    "%store -r\n",
    "%store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training data:  (80000, 32) and labels:  (80000,)\n",
      " \n",
      "Test data:\n",
      "Total 20 (4000, 32) arrays for SNR values:\n",
      "[-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n"
     ]
    }
   ],
   "source": [
    "print(\"Training data: \", X_32train_std.shape, \"and labels: \", y_32_train.shape)\n",
    "print(\" \")\n",
    "print(\"Test data:\")\n",
    "print(\"Total\", len(X_32test_std), X_32test_std[18].shape, \"arrays for SNR values:\")\n",
    "print(sorted(X_32test_std.keys()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# tf.reset_default_graph()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create validation set required for early stopping"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Validation set data (40000, 32) and labels (40000,)\n"
     ]
    }
   ],
   "source": [
    "X_val = []\n",
    "y_val = []\n",
    "\n",
    "X_test_new = defaultdict(list)\n",
    "y_test_new = defaultdict(list)\n",
    "\n",
    "for snr in snrs:\n",
    "    n_test = X_32test_std[snr].shape[0]\n",
    "    X_val.append(X_32test_std[snr][:(n_test*0.5)])\n",
    "    y_val.append(y_32_test[snr][:(n_test*0.5)])\n",
    "    X_test_new[snr] = X_32test_std[snr][(n_test*0.5):]\n",
    "    y_test_new[snr] = y_32_test[snr][(n_test*0.5):]\n",
    "    \n",
    "X_val = np.vstack(np.asarray(X_val))\n",
    "y_val =np.hstack(np.asarray(y_val))\n",
    "\n",
    "print(\"Validation set data\", X_val.shape, \"and labels\", y_val.shape)\n",
    "\n",
    "X_32test_std = X_test_new\n",
    "y_32_test = y_test_new\n",
    "X_32_val = X_val \n",
    "y_32_val = y_val"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Design and train the DNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\tValidation loss: 1.398042\tMinimum loss: 1.398042\tAccuracy on validation set: 0.42\n",
      "1\tValidation loss: 1.319292\tMinimum loss: 1.319292\tAccuracy on validation set: 0.45\n",
      "2\tValidation loss: 1.308735\tMinimum loss: 1.308735\tAccuracy on validation set: 0.46\n",
      "3\tValidation loss: 1.284621\tMinimum loss: 1.284621\tAccuracy on validation set: 0.47\n",
      "4\tValidation loss: 1.243694\tMinimum loss: 1.243694\tAccuracy on validation set: 0.49\n",
      "5\tValidation loss: 1.230867\tMinimum loss: 1.230867\tAccuracy on validation set: 0.49\n",
      "6\tValidation loss: 1.201689\tMinimum loss: 1.201689\tAccuracy on validation set: 0.50\n",
      "7\tValidation loss: 1.195004\tMinimum loss: 1.195004\tAccuracy on validation set: 0.50\n",
      "8\tValidation loss: 1.194342\tMinimum loss: 1.194342\tAccuracy on validation set: 0.50\n",
      "9\tValidation loss: 1.191829\tMinimum loss: 1.191829\tAccuracy on validation set: 0.50\n",
      "10\tValidation loss: 1.185067\tMinimum loss: 1.185067\tAccuracy on validation set: 0.50\n",
      "11\tValidation loss: 1.181152\tMinimum loss: 1.181152\tAccuracy on validation set: 0.51\n",
      "12\tValidation loss: 1.178728\tMinimum loss: 1.178728\tAccuracy on validation set: 0.51\n",
      "13\tValidation loss: 1.175459\tMinimum loss: 1.175459\tAccuracy on validation set: 0.51\n",
      "14\tValidation loss: 1.172844\tMinimum loss: 1.172844\tAccuracy on validation set: 0.51\n",
      "15\tValidation loss: 1.166669\tMinimum loss: 1.166669\tAccuracy on validation set: 0.51\n",
      "16\tValidation loss: 1.172543\tMinimum loss: 1.166669\tAccuracy on validation set: 0.51\n",
      "17\tValidation loss: 1.169910\tMinimum loss: 1.166669\tAccuracy on validation set: 0.51\n",
      "18\tValidation loss: 1.171443\tMinimum loss: 1.166669\tAccuracy on validation set: 0.51\n",
      "19\tValidation loss: 1.169554\tMinimum loss: 1.166669\tAccuracy on validation set: 0.51\n",
      "20\tValidation loss: 1.165980\tMinimum loss: 1.165980\tAccuracy on validation set: 0.51\n",
      "21\tValidation loss: 1.170280\tMinimum loss: 1.165980\tAccuracy on validation set: 0.51\n",
      "22\tValidation loss: 1.167675\tMinimum loss: 1.165980\tAccuracy on validation set: 0.51\n",
      "23\tValidation loss: 1.166127\tMinimum loss: 1.165980\tAccuracy on validation set: 0.51\n",
      "24\tValidation loss: 1.162242\tMinimum loss: 1.162242\tAccuracy on validation set: 0.51\n",
      "25\tValidation loss: 1.160749\tMinimum loss: 1.160749\tAccuracy on validation set: 0.52\n",
      "26\tValidation loss: 1.164775\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "27\tValidation loss: 1.169999\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "28\tValidation loss: 1.173177\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "29\tValidation loss: 1.174446\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "30\tValidation loss: 1.173025\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "31\tValidation loss: 1.168777\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "32\tValidation loss: 1.161647\tMinimum loss: 1.160749\tAccuracy on validation set: 0.52\n",
      "33\tValidation loss: 1.169902\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "34\tValidation loss: 1.163606\tMinimum loss: 1.160749\tAccuracy on validation set: 0.51\n",
      "35\tValidation loss: 1.160651\tMinimum loss: 1.160651\tAccuracy on validation set: 0.51\n",
      "36\tValidation loss: 1.160353\tMinimum loss: 1.160353\tAccuracy on validation set: 0.52\n",
      "37\tValidation loss: 1.161080\tMinimum loss: 1.160353\tAccuracy on validation set: 0.52\n",
      "38\tValidation loss: 1.162115\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "39\tValidation loss: 1.167296\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "40\tValidation loss: 1.172772\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "41\tValidation loss: 1.176629\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "42\tValidation loss: 1.171462\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "43\tValidation loss: 1.166720\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "44\tValidation loss: 1.167470\tMinimum loss: 1.160353\tAccuracy on validation set: 0.52\n",
      "45\tValidation loss: 1.168746\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "46\tValidation loss: 1.169740\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "47\tValidation loss: 1.173677\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "48\tValidation loss: 1.178855\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "49\tValidation loss: 1.181764\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "50\tValidation loss: 1.179192\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "51\tValidation loss: 1.181873\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "52\tValidation loss: 1.185895\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "53\tValidation loss: 1.190131\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "54\tValidation loss: 1.188639\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "55\tValidation loss: 1.186393\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "56\tValidation loss: 1.194995\tMinimum loss: 1.160353\tAccuracy on validation set: 0.51\n",
      "** EARLY STOPPING ** \n",
      " \n",
      "INFO:tensorflow:Restoring parameters from ./DNN4layer_regtech_maxnorm\n",
      "Training and testing took 2.089649 minutes\n"
     ]
    }
   ],
   "source": [
    "# ----------------- Initialize parameters -----------------------\n",
    "\n",
    "\n",
    "n_hidden1 = 256\n",
    "n_hidden2 = 256\n",
    "n_hidden3 = 256\n",
    "n_hidden4 = 256\n",
    "\n",
    "n_outputs = 8\n",
    "\n",
    "X = tf.placeholder(tf.float32, shape=(None, 32))\n",
    "y = tf.placeholder(tf.int64, shape=(None))\n",
    "training_ = tf.placeholder_with_default(False, shape=[])\n",
    "\n",
    "weight_init = tf.contrib.layers.xavier_initializer()\n",
    "activation_func = tf.nn.elu\n",
    "\n",
    "max_clip_value = 1.0\n",
    "\n",
    "# ------------------- Define layers -----------------------\n",
    "\n",
    "def dense_layer(input_layer, n_neurons, kernel_init, activation, name):\n",
    "    fully_conn = tf.layers.dense(inputs = input_layer, units = n_neurons, activation = activation,\n",
    "                                kernel_initializer = kernel_init, name = name)\n",
    "    return fully_conn\n",
    "        \n",
    "dense_layer1 = dense_layer(X, n_hidden1, weight_init, activation_func, \"dense1\")\n",
    "\n",
    "dl1_weights = tf.get_default_graph().get_tensor_by_name(\"dense1/kernel:0\")\n",
    "clipped1 = tf.clip_by_norm(dl1_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl1_clipped = tf.assign(dl1_weights, clipped1)\n",
    "\n",
    "dense_layer2 = dense_layer(dense_layer1, n_hidden2, weight_init, activation_func, \"dense2\")\n",
    "\n",
    "dl2_weights = tf.get_default_graph().get_tensor_by_name(\"dense2/kernel:0\")\n",
    "clipped2 = tf.clip_by_norm(dl2_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl2_clipped = tf.assign(dl2_weights, clipped2)\n",
    "\n",
    "dense_layer3 = dense_layer(dense_layer2, n_hidden3, weight_init, activation_func, \"dense3\")\n",
    "\n",
    "dl3_weights = tf.get_default_graph().get_tensor_by_name(\"dense3/kernel:0\")\n",
    "clipped3 = tf.clip_by_norm(dl3_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl3_clipped = tf.assign(dl3_weights, clipped3)\n",
    "\n",
    "dense_layer4 = dense_layer(dense_layer3, n_hidden4, weight_init, activation_func, \"dense4\")\n",
    "\n",
    "dl4_weights = tf.get_default_graph().get_tensor_by_name(\"dense4/kernel:0\")\n",
    "clipped4 = tf.clip_by_norm(dl4_weights, clip_norm = max_clip_value, axes=1)\n",
    "dl4_clipped = tf.assign(dl4_weights, clipped4)\n",
    "\n",
    "logits = tf.layers.dense(dense_layer4, n_outputs)\n",
    "softmax_activations = tf.nn.softmax(logits)\n",
    "\n",
    "# ----------------- Specify performance measure ----------------------\n",
    "\n",
    "xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)\n",
    "loss = tf.reduce_mean(xentropy)\n",
    "\n",
    "optimizer = tf.train.AdamOptimizer()\n",
    "training_op = optimizer.minimize(loss)\n",
    "\n",
    "correct = tf.nn.in_top_k(logits, y, 1)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))\n",
    "        \n",
    "# ------------------ Execution phase ----------------------------------    \n",
    "\n",
    "n_epochs = 1000\n",
    "batch_size = 1024\n",
    "n_train = X_train_std.shape[0]\n",
    "n_iter = n_train//batch_size\n",
    "\n",
    "saver = tf.train.Saver()\n",
    "\n",
    "min_loss = np.infty\n",
    "epochs_without_improvement = 0 \n",
    "max_epochs_without_improvement = 20   \n",
    "\n",
    "acc_test = defaultdict(list)\n",
    "\n",
    "start = time()\n",
    "path = \"./DNN4layer_regtech_maxnorm\"\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    tf.global_variables_initializer().run()\n",
    "    for epoch in range(n_epochs):\n",
    "        for iteration in range(n_iter):\n",
    "            rand_indices = np.random.choice(n_train,batch_size) #select random samples to form mini batches   \n",
    "            X_batch, y_batch = X_32train_std[rand_indices], y_32_train[rand_indices]\n",
    "            sess.run(training_op, feed_dict={X: X_batch, y: y_batch,  training_: True})\n",
    "        valid_loss, acc_val = sess.run([loss, accuracy], feed_dict={X: X_32_val, y: y_32_val, training_: True})\n",
    "        \n",
    "        # Early stopping \n",
    "        \n",
    "        if valid_loss < min_loss:\n",
    "            save_path = saver.save(sess, path)\n",
    "            min_loss = valid_loss\n",
    "            epochs_without_improvement = 0\n",
    "        else:\n",
    "            epochs_without_improvement += 1\n",
    "            if epochs_without_improvement > max_epochs_without_improvement:\n",
    "                print(\"** EARLY STOPPING ** \")\n",
    "                break\n",
    "        print(\"{}\\tValidation loss: {:.6f}\\tMinimum loss: {:.6f}\\tAccuracy on validation set: {:.2f}\".format(\n",
    "            epoch, valid_loss, min_loss, acc_val))\n",
    "\n",
    "print(\" \")\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    for snr in snrs:\n",
    "        acc_test[snr] = accuracy.eval(feed_dict={X: X_32test_std[snr], y: y_32_test[snr]})\n",
    "\n",
    "print(\"Training and testing took %f minutes\"%(float(time() - start)/60))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Test the DNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DNN's test accuracy on -20 dB SNR samples =  0.134\n",
      "DNN's test accuracy on -18 dB SNR samples =  0.1365\n",
      "DNN's test accuracy on -16 dB SNR samples =  0.129\n",
      "DNN's test accuracy on -14 dB SNR samples =  0.1385\n",
      "DNN's test accuracy on -12 dB SNR samples =  0.1275\n",
      "DNN's test accuracy on -10 dB SNR samples =  0.191\n",
      "DNN's test accuracy on -8 dB SNR samples =  0.2955\n",
      "DNN's test accuracy on -6 dB SNR samples =  0.369\n",
      "DNN's test accuracy on -4 dB SNR samples =  0.407\n",
      "DNN's test accuracy on -2 dB SNR samples =  0.482\n",
      "DNN's test accuracy on 0 dB SNR samples =  0.586\n",
      "DNN's test accuracy on 2 dB SNR samples =  0.7015\n",
      "DNN's test accuracy on 4 dB SNR samples =  0.812\n",
      "DNN's test accuracy on 6 dB SNR samples =  0.828\n",
      "DNN's test accuracy on 8 dB SNR samples =  0.838\n",
      "DNN's test accuracy on 10 dB SNR samples =  0.828\n",
      "DNN's test accuracy on 12 dB SNR samples =  0.834\n",
      "DNN's test accuracy on 14 dB SNR samples =  0.833\n",
      "DNN's test accuracy on 16 dB SNR samples =  0.834\n",
      "DNN's test accuracy on 18 dB SNR samples =  0.8365\n"
     ]
    }
   ],
   "source": [
    "for snr in snrs:\n",
    "    print(\"DNN's test accuracy on %d dB SNR samples = \"%(snr), acc_test[snr])   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "##  Visualize DNN's performance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f50641bbac8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.style.use('classic')\n",
    "%matplotlib inline\n",
    "\n",
    "acc_test = sorted(acc_test.items())\n",
    "new_acc = []\n",
    "for i in range(len(acc_test)):\n",
    "    new_acc.append(acc_test[i][1])\n",
    "acc_test_values = new_acc \n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "x = snrs\n",
    "y = list(acc_test_values)\n",
    "plt.plot(x, y, marker=\"o\", linewidth=2.0, linestyle='dashed', color='royalblue')\n",
    "plt.axis([-20, 20, 0, 1])\n",
    "plt.xticks(np.arange(min(x), max(x)+1, 2.0))\n",
    "plt.yticks(np.arange(0, 1, 0.10))\n",
    "\n",
    "ttl = plt.title('SNR vs Accuracy', fontsize=16)\n",
    "ttl.set_weight('bold')\n",
    "plt.xlabel('SNR (dB)', fontsize=14)\n",
    "plt.ylabel('Test accuracy', fontsize=14)\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Restoring parameters from ./DNN4layer_regtech_maxnorm\n",
      "Confusion Matrix\n",
      "       8PSK  BPSK  CPFSK  GFSK  PAM4  QAM16  QAM64  QPSK\n",
      "8PSK   0.81  0.00   0.00  0.00  0.00   0.08   0.10  0.00\n",
      "BPSK   0.00  1.00   0.00  0.00  0.00   0.00   0.00  0.00\n",
      "CPFSK  0.01  0.00   0.97  0.00  0.00   0.01   0.02  0.00\n",
      "GFSK   0.02  0.00   0.01  0.96  0.00   0.00   0.01  0.00\n",
      "PAM4   0.00  0.01   0.00  0.00  0.98   0.00   0.01  0.00\n",
      "QAM16  0.02  0.00   0.00  0.00  0.00   0.45   0.52  0.00\n",
      "QAM64  0.02  0.00   0.00  0.00  0.00   0.49   0.49  0.00\n",
      "QPSK   0.03  0.01   0.00  0.00  0.01   0.05   0.02  0.88\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5050217748>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Confusion Matrix\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    Z = logits.eval(feed_dict = {X : X_32test_std[18]})\n",
    "    predicted_18dB = np.argmax(Z, axis = 1)\n",
    "    \n",
    "from sklearn.metrics import confusion_matrix\n",
    "%matplotlib inline\n",
    "\n",
    "classes = ['8PSK', 'BPSK', 'CPFSK', 'GFSK', 'PAM4', 'QAM16', 'QAM64', 'QPSK']\n",
    "conf_matrix = confusion_matrix(predicted_18dB, y_32_test[18])  \n",
    "\n",
    "conf_matrix = conf_matrix.astype('float') / conf_matrix.sum(axis=1)[:, np.newaxis]\n",
    "conf_matrix = conf_matrix.round(decimals = 2)\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(data = conf_matrix, columns = classes, index = classes) \n",
    "print(\"Confusion Matrix\")\n",
    "print(df)\n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "plt.imshow(conf_matrix, interpolation = 'nearest', cmap = plt.cm.Purples)\n",
    "ticks = np.arange(len(classes))\n",
    "plt.title(\"Confusion Matrix\")\n",
    "plt.xticks(ticks, classes, rotation=45)\n",
    "plt.yticks(ticks, classes)\n",
    "\n",
    "plt.ylabel('True class')\n",
    "plt.xlabel('Predicted class')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.colorbar()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
